/*
 * @Author: wuqingchun
 * @Date: 2024-06-29 16:38:57
 * @Description: http 协议解析器
 * @LastEditors: wuqingchun
 * @LastEditTime: 2024-06-29 17:39:22
 */

#ifndef __HTTP_PARSER_H__
#define __HTTP_PARSER_H__

#include <string>

#include "http.h"
#include "http_event.h"

#define HTTP_METHOD_UNKNOWN                   0x0001
#define HTTP_METHOD_GET                       0x0002
#define HTTP_METHOD_HEAD                      0x0004
#define HTTP_METHOD_POST                      0x0008
#define HTTP_METHOD_PUT                       0x0010
#define HTTP_METHOD_DELETE                    0x0020
#define HTTP_METHOD_MKCOL                     0x0040
#define HTTP_METHOD_COPY                      0x0080
#define HTTP_METHOD_MOVE                      0x0100
#define HTTP_METHOD_OPTIONS                   0x0200
#define HTTP_METHOD_PROPFIND                  0x0400
#define HTTP_METHOD_PROPPATCH                 0x0800
#define HTTP_METHOD_LOCK                      0x1000
#define HTTP_METHOD_UNLOCK                    0x2000
#define HTTP_METHOD_PATCH                     0x4000
#define HTTP_METHOD_TRACE                     0x8000

enum class EnumHTTPParserState
{
    ST_START = 0,
    ST_METHOD,
    ST_SPACES_BEFORE_URI,
    ST_SCHEMA,
    ST_SCHEMA_SLASH,
    ST_SCHEMA_SLASH_SLASH,
    ST_HOST_START,
    ST_HOST,
    ST_HOST_END,
    ST_HOST_IP_LITERAL,
    ST_PORT,
    ST_HOST_HTTP_09,
    ST_AFTER_SLASH_IN_URI,
    ST_CHECK_URI,
    ST_CHECK_URI_HTTP_09,
    ST_URI,
    ST_HTTP_09,
    ST_HTTP_H,
    ST_HTTP_HT,
    ST_HTTP_HTT,
    ST_HTTP_HTTP,
    ST_FIRST_MAJOR_DIGIT,
    ST_MAJOR_DIGIT,
    ST_FIRST_MINOR_DIGIT,
    ST_MINOR_DIGIT,
    ST_SPACES_AFTER_DIGIT,
    ST_ALMOST_DONE
};

class CHTTPParser
{
private:
    static constexpr char HTTP_PARSER_LF = '\n';
    static constexpr char HTTP_PARSER_CR = '\r';
    static const constexpr char* HTTP_PARSER_CRLF = "\r\n";
    static constexpr size_t HTTP_METHOD_MAX_LEN = 16;

public:
    int32_t OnRecv(IHTTPEvent& refEvent, HTTP_BUF_S& refBuf);
private:
    EnumHTTPParserState m_enState = EnumHTTPParserState::ST_START;
    uint32_t m_uiMethod;
    char m_szMethod[HTTP_METHOD_MAX_LEN];
    size_t m_ulMethodIndex = 0;
    std::string m_strMethod;

};


// 小端序
#define http_str3_cmp(m, c0, c1, c2, c3)                                       \
    m[0] == c0 && m[1] == c1 && m[2] == c2

#define http_str3Ocmp(m, c0, c1, c2, c3)                                       \
    m[0] == c0 && m[2] == c2 && m[3] == c3

#define http_str4cmp(m, c0, c1, c2, c3)                                        \
    m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3

#define http_str5cmp(m, c0, c1, c2, c3, c4)                                    \
    m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 && m[4] == c4

#define http_str6cmp(m, c0, c1, c2, c3, c4, c5)                                \
    m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3                      \
        && m[4] == c4 && m[5] == c5

#define http_str7_cmp(m, c0, c1, c2, c3, c4, c5, c6, c7)                       \
    m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3                      \
        && m[4] == c4 && m[5] == c5 && m[6] == c6

#define http_str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7)                        \
    m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3                      \
        && m[4] == c4 && m[5] == c5 && m[6] == c6 && m[7] == c7

#define http_str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8)                    \
    m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3                      \
        && m[4] == c4 && m[5] == c5 && m[6] == c6 && m[7] == c7 && m[8] == c8

#endif //__HTTP_PARSER_H__